package com.yuncheng.spcyApi.flow;

/**
 * @author hua
 */

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.yuncheng.entity.YcSysUser;
import com.yuncheng.spcyApi.vo.common.HttpResultVo;
import com.yuncheng.spcyApi.vo.spcy.ZltxwjXgwjVo;
import com.yuncheng.vo.GetKsKz;
import com.yuncheng.vo.CurrentUserVo;
import com.yuncheng.vo.HttpResult;
import org.apache.commons.collections.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.yuncheng.spcyApi.busService.BusService;
import com.yuncheng.spcyApi.config.SpcyMinioUtils;
import com.yuncheng.spcyApi.constant.common.BusinessConstant;
import com.yuncheng.spcyApi.constant.common.LogConstant;
import com.yuncheng.spcyApi.constant.common.SpcyConstant;
import com.yuncheng.spcyApi.constant.flow.FlowNodeConstant;
import com.yuncheng.spcyApi.entity.*;
import com.yuncheng.exception.BusinessException;
import com.yuncheng.spcyApi.service.*;
import com.yuncheng.spcyApi.service.impl.YcSysUserServiceImpl;
import com.yuncheng.spcyApi.utils.*;
import com.yuncheng.spcyApi.vo.common.Result;
import com.yuncheng.spcyApi.vo.flow.AgentVo;
import com.yuncheng.spcyApi.vo.flow.CommonFlowVo;
import com.yuncheng.spcyApi.vo.flow.VerifyNowNextJobDbrVo;
import com.yuncheng.spcyApi.vo.spcy.SpcyReturnVo;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import utils.DateConversionUtils;
import utils.LogUtils;
import utils.ObjectToMapUtils;
import utils.Util;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * 质量体系文件流程
 * @author hua
 */
@Component(value = "txwjFlowService")
public class TxwjFlowService {
    private static final Logger log = LoggerFactory.getLogger(TxwjFlowService.class);

    @Resource
    @Lazy
    private ISysUserFgldService sysUserFgldService;

    @Resource
    @Lazy
    private YcSysUserServiceImpl ycSysUserService;

    @Resource
    @Lazy
    private ISpcyZltxwjBasicService spcyZltxwjBasicService;

    @Resource
    private ISpcyZltxwjTypeService spcyZltxwjTypeService;

    @Resource
    @Lazy
    private ISpcyZltxwjFlowService spcyZltxwjFlowService;

    @Resource
    @Lazy
    private ISpcyZltxwjHistoryService spcyZltxwjHistoryService;

    @Resource
    @Lazy
    private ISpcySqsxWjjlService spcySqsxWjjlService;

    @Resource
    private BusinessConstant businessConstant;

    @Resource
    private LocalFileUploadUtils localFileUploadUtils;

    @Resource
    private WordPdfUtils wordPdfUtils;

    @Resource
    private SpcyMinioUtils spcyMinioUtils;

    @Resource
    @Lazy
    private BusService busService;

    @Resource
    @Lazy
    private ISpcySqsxJobService spcySqsxJobService;

    @Resource
    @Lazy
    private ISysFlowNodeService sysFlowNodeService;

    @Resource
    @Lazy
    private FlowNodeService flowNodeService;

    @Resource
    @Lazy
    private ISpcyLogService spcyLogService;

    @Resource
    private HnCaUtils hnCaUtils;

    @Autowired
    @Qualifier("asyncMiddleTask")
    private Executor executor;

    @Resource
    private ISpcyZltxwjXgpxwjService spcyZltxwjXgpxwjService;

    /**
     * 处理流程
     * @param flowVo
     * @param jobId
     * @param submitType
     * @param opinion
     * @return
     */
    public Result handleFlow(CommonFlowVo flowVo, String jobId, String pid, String submitType, String opinion){
        if (StringUtils.isBlank(jobId)){
            throw new BusinessException("流程任务参数为空！");
        }
        // 当前流程任务
        SpcySqsxJob nowJob = spcySqsxJobService.getById(jobId);;

        if (nowJob == null){
            return Result.error("当前流程任务不存在，请重试");
        }

        pid = nowJob.getFpid();
        if (StringUtils.isBlank(pid)){
            throw new BusinessException("业务参数为空！");
        }

        // 提交按钮
        if (submitType.equals(SpcyFlowConstant.SUBMIT_TYPE_SUBMIT)) {
            if (nowJob == null) {
                return Result.error("当前流程任务不存在");
            }
        }

        if (nowJob.getFhjmc().equals(SpcyFlowConstant.ZLTXWJ_HJMC_KSFH)){

            String deptName = "";
            SpcyZltxwjFlow zltxwj = null;
            if (submitType.equals(SpcyFlowConstant.SUBMIT_TYPE_SUBMIT)) {
                zltxwj = spcyZltxwjFlowService.getById(pid);
                if (zltxwj != null) {
                    deptName = zltxwj.getFsqks();
                }

                if (zltxwj.getFxglx().equals(SpcyConstant.Zltxwj_Xdlx_XGPX)) {
                    flowVo.setNextNode(SpcyFlowConstant.ZLTXWJ_HJMC_XGXGPJ);
                } else {
                    // 申请者为 药品生产和医疗器械，直接提交到下下个环节
                    if (deptName.equals(SpcyConstant.YPSC_ORG_NAME)) {
                        flowVo.setNextNode(SpcyFlowConstant.ZLTXWJ_HJMC_GLZDB);

                    } else if (deptName.equals(SpcyConstant.YPZC_ORG_NAME)) {
                        flowVo.setNextNode(SpcyFlowConstant.ZLTXWJ_HJMC_GLZDB);
                    } else {
                        flowVo.setNextNode("");
                    }
                }
            }

            // 流程环节处理
            Result httpResult = handleNodeName(flowVo, submitType, nowJob, pid, opinion);
            if (!httpResult.isSuccess()) {
                return httpResult;
            }

            if (submitType.equals(SpcyFlowConstant.SUBMIT_TYPE_SUBMIT)
                    && zltxwj.getFxglx().equals(SpcyConstant.Zltxwj_Xdlx_XGPX)){

                // 初始化宣贯培训人员的文件记录
                Result result1 = this.initXgpxwjWithXfxxryIds(zltxwj.getFxglx(), pid, zltxwj.getFxgxxryid());
                if (!result1.isSuccess()) {
                    log.error("初始化宣贯培训人员的文件记录-错误：{}", result1.getMessage());
                }

                // 发布-宣贯学习-环节子流程
                Result result = this.releaseXgxxJob(pid, zltxwj, nowJob);
                if (!result.isSuccess()) {
                    log.error("发布-宣贯学习-环节子流程-错误：{}", result.getMessage());
                }

            }

        }else if (nowJob.getFhjmc().equals(SpcyFlowConstant.ZLTXWJ_HJMC_FGLD)){

            if (submitType.equals(SpcyFlowConstant.SUBMIT_TYPE_SUBMIT)) {
                Map nextDbr = this.getNowJobInNextDbrAndHandlePageUrl(jobId, nowJob);
                List<AgentVo> dbrListByMap = this.getDbrListByMap(nextDbr);
                // 验证当前待办人与下一个环节待办人是否相同
                VerifyNowNextJobDbrVo dbrVo = this.verifyNextAndNowJobDbrSfxt(dbrListByMap, nowJob, SpcyFlowConstant.ZLTXWJ_HJMC_GLZDB);
                if (dbrVo != null) {
                    if (StringUtils.isNotBlank(dbrVo.getErrorMsg())) {
                        throw new BusinessException(dbrVo.getErrorMsg());
                    }

                    flowVo.setNextNode(dbrVo.getNextNode());
                    flowVo.setDbrid(dbrVo.getNextNodeDbrId());
                }
            }

            // 流程环节处理
            Result httpResult = handleNodeName(flowVo, submitType, nowJob, pid, opinion);
            if (!httpResult.isSuccess()) {
                return httpResult;
            }

        }else if (nowJob.getFhjmc().equals(SpcyFlowConstant.ZLTXWJ_HJMC_ZXLD)){

            if (submitType.equals(SpcyFlowConstant.SUBMIT_TYPE_SUBMIT)) {
                SpcyZltxwjFlow zltxwj = spcyZltxwjFlowService.getById(pid);
                if (zltxwj == null) {
                    log.error("前质量体系文件数据不存在，请刷新重试并联系管理员！");
                    throw new BusinessException("业务数据不存在！");
                }

            /*if (StringUtils.isNotBlank(zltxwj.getFxglx())
                    && (zltxwj.getFxglx().equals(SpcyConstant.Zltxwj_Xdlx_Xd)
                    || zltxwj.getFxglx().equals(SpcyConstant.Zltxwj_Xdlx_Xz))){
            }*/
                flowVo.setNextNode(SpcyFlowConstant.ZLTXWJ_HJMC_XDSH);
            }

            // 流程环节处理
            Result httpResult = handleNodeName(flowVo, submitType, nowJob, pid, opinion);
            if (!httpResult.isSuccess()) {
                return httpResult;
            }

        }else if (nowJob.getFhjmc().equals(SpcyFlowConstant.ZLTXWJ_HJMC_XDSH)){

            // 流程环节处理
            Result httpResult = handleNodeName(flowVo, submitType, nowJob, pid, opinion);
            if (!httpResult.isSuccess()){
                return httpResult;
            }

            if (submitType.equals(SpcyFlowConstant.SUBMIT_TYPE_SUBMIT)){
                SpcyZltxwjFlow zltxwj = spcyZltxwjFlowService.getById(pid);
                if (zltxwj == null){
                    log.error("前质量体系文件数据不存在，请刷新重试并联系管理员！");
                }else {
                    hnCaUtils.fileCaInZltxwjFlow(pid, zltxwj);

                    // 发布-宣贯学习-环节子流程
                    Result result = this.releaseXgxxJob(pid, zltxwj, nowJob);
                    if (!result.isSuccess()) {
                        log.error(result.getMessage());
                    }
                }
            }

        }else if (nowJob.getFhjmc().equals(SpcyFlowConstant.ZLTXWJ_HJMC_XGXX)){

            this.completionXgxxJob(nowJob.getId(), nowJob, flowVo.getOpinion());

        }else if (nowJob.getFhjmc().equals(SpcyFlowConstant.ZLTXWJ_HJMC_XGXGPJ)){

            if (submitType.equals(SpcyFlowConstant.SUBMIT_TYPE_SUBMIT)) {
                SpcyZltxwjFlow zltxwj = spcyZltxwjFlowService.getById(pid);

                if (zltxwj.getFxglx().equals(SpcyConstant.Zltxwj_Xdlx_XGPX)) {
                    flowVo.setNextNode(SpcyFlowConstant.ZLTXWJ_HJMC_WJSS);
                }
            }

            // 流程环节处理
            Result httpResult = handleNodeName(flowVo, submitType, nowJob, pid, opinion);
            if (!httpResult.isSuccess()) {
                return httpResult;
            }

        }else if (nowJob.getFhjmc().equals(SpcyFlowConstant.ZLTXWJ_HJMC_END)){

            // 流程环节处理
            Result httpResult = handleNodeName(flowVo, submitType, nowJob, pid, opinion);
            if (!httpResult.isSuccess()){
                return httpResult;

            }else if (submitType.equals(SpcyFlowConstant.SUBMIT_TYPE_SUBMIT)){
                SpcyZltxwjFlow zltxwj = spcyZltxwjFlowService.getById(pid);

                if (zltxwj != null){
                    // 更新质量体系文件-修订状态
                    if (StringUtils.isNotBlank(zltxwj.getFpid())) {
                        LambdaUpdateWrapper<SpcyZltxwjBasic> updateWrapper = new LambdaUpdateWrapper<>();
                        updateWrapper.eq(SpcyZltxwjBasic::getId, zltxwj.getFpid());

                        SpcyZltxwjBasic updateBean = new SpcyZltxwjBasic();
                        updateBean.setFxdzt("");
                        spcyZltxwjBasicService.update(updateBean, updateWrapper);
                    }
                    zltxwj.setFlczt(SpcyFlowConstant.LCZT_LCBJ); // 流程结束
                    spcyZltxwjFlowService.updateById(zltxwj);
                }

                String finalPid = pid;
                Integer resultFlag = 1;
                AtomicReference<String> errorMsg = new AtomicReference<>("");
                CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {

                    Result result = this.ysFlowToZltxwjBasic(finalPid);// 移送文件到 质量体系文件资源库
                    if (!result.isSuccess()){
                        throw new BusinessException(result.getMessage());
                    }
                    return 1;
                }, executor).handle((res, exception)->{
                    if (exception != null) {
                        errorMsg.set(exception.getMessage());
                        return 0;
                    }else{
                        return 1;
                    }
                });

                try {
                    resultFlag = future.get();
                } catch (InterruptedException e) {
                    log.error("[InterruptedException]移送文件到质量体系文件资源库: {}", e.getMessage());
                } catch (ExecutionException e) {
                    log.error("[InterruptedException]移送文件到质量体系文件资源库: {}", e.getMessage());
                }

                if (resultFlag == 0){
                    throw new BusinessException(errorMsg.get());
                }

            }

        }else if (nowJob.getFhjmc().equals(SpcyFlowConstant.ZLTXWJ_HJMC_WJSS)){

            // 流程环节处理
            Result httpResult = handleNodeName(flowVo, submitType, nowJob, pid, opinion);
            if (!httpResult.isSuccess()) {
                return httpResult;
            }

            if (submitType.equals(SpcyFlowConstant.SUBMIT_TYPE_SUBMIT)){
                LambdaUpdateWrapper<SpcyZltxwjFlow> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.eq(SpcyZltxwjFlow::getId, pid);

                SpcyZltxwjFlow updateBean = new SpcyZltxwjFlow();
                updateBean.setFlczt(SpcyFlowConstant.LCZT_LCBJ); // 流程结束
                spcyZltxwjFlowService.update(updateBean, updateWrapper);
            }

        }else {

            // 流程环节处理
            Result httpResult = handleNodeName(flowVo, submitType, nowJob, pid, opinion);
            if (!httpResult.isSuccess()) {
                return httpResult;
            }
        }

        return Result.ok("操作成功");
    }

    /**
     * 流程环节处理
     * @param pid 业务id
     * @param flowVo 需要修改的字段内容
     * @param job 流程任务job
     * @param opinion 办理意见
     * @param submitType 提交、保存类型
     * @return true(),false(提示信息)
     */
    public Result handleNodeName(CommonFlowVo flowVo, String submitType, SpcySqsxJob job, String pid, String opinion){
        HashMap<String, Object> map = flowVo.getMap();
        String smgflag = flowVo.getSmgflag(); // 短信发送标志
        String smsContent = flowVo.getSmsContent(); // 发送短信内容

        Result res = null;

        // 保存按钮
        if (submitType.equals(SpcyFlowConstant.SUBMIT_TYPE_SAVE)){
            res = this.updateJbxx(map, pid, job);
            if (!res.isSuccess()){
                return res;
            }else {
                return Result.ok("保存成功");
            }
        }

        // 提交按钮
        if (submitType.equals(SpcyFlowConstant.SUBMIT_TYPE_SUBMIT)){
            res = this.updateJbxx(map, pid, job);
            if (!res.isSuccess()){
                return res;
            }

            if (job == null){
                throw new BusinessException("当前流程任务不存在！");
            }

            if (StringUtils.isBlank(job.getFhjmc())){
                throw new BusinessException("当前流程任务环节名称丢失！");
            }

            // 流程任务id
            String jobid = job.getId();

            // 提交流程任务,待办人是否为空，指定待办人
            if (StringUtils.isBlank(flowVo.getDbrid())) {
                // 按审查模式-提交-流程任务
                res = this.passJob(pid, jobid, job, opinion, flowVo.getNextNode(),flowVo.getNextNodeId(), null);
            }else {
                // 按审查模式-提交-流程任务
                res = this.passJob(pid, jobid, job, opinion, flowVo.getNextNode(),flowVo.getNextNodeId(),flowVo.getDbrid());
            }

            if (!res.isSuccess()){
                return res;
            }else {
                /**
                 * 接收返回的流程任务，如果返回的流程任务id不相等，发送短信
                 * 发送下环节短信
                 */
                if (StringUtils.isNotBlank(smgflag) && (smgflag.equals("是") || smgflag.equals("true"))){
                    busService.sendSmsToNextJob(jobid,smsContent);
                }
            }
        }

        return Result.ok("提交成功");
    }

    /**
     * 初始化流程
     * @param pid 业务id
     * @param currentUser 当前登陆用户
     * @param isSendSms 是否发送短信
     * @return
     */
    public Result createProcess(String pid, CurrentUserVo currentUser, boolean isSendSms){

        String lcmbCode = SpcyFlowConstant.ZLTXWJ_FLOW_CODE;

        //获取流程模板的第一个环节
        SysFlowTemple code = sysFlowNodeService.getCode(lcmbCode);

        List<SysFlowNode> node = sysFlowNodeService.getFirstNode(code.getId());

        List<SpcySqsxJob> jobList = spcySqsxJobService.list(new LambdaQueryWrapper<SpcySqsxJob>()
                .eq(SpcySqsxJob::getFpid, pid)
                .eq(SpcySqsxJob::getFnodeid, node.get(0).getId()));
        if (CollectionUtils.isNotEmpty(jobList)){
            return Result.error("当前申请事项环节["+node.get(0).getFjdmc()+"】已经初始化了!");
        }

        Result result = flowNodeService.createJob(lcmbCode,pid,"",node.get(0),null,null,currentUser);
        if (!result.isSuccess()){
            return result;
        }else {
            if (isSendSms) {
                SpcySqsxJob job = (SpcySqsxJob) result.getResult();
                if (job != null) {
                    String nextNodeSmsContent = busService.getNextNodeSmsContent(job, null);
                    busService.sendSmsToNodeDbr(job.getFdbrid(), job.getFlcmc() + "-" + job.getFhjmc(), nextNodeSmsContent);
                }
            }
        }

        return result;
    }

    /**
     * 提交流程
     * @param pid 业务id
     * @param jobid 流程任务id
     * @param job 当前流程任务
     * @param opinion 办理意见
     * @param nextNodeName 下环节结点名称
     * @param nextNodeId 下环节结点id
     * @param nextNodeDbrIds 下环节待办人
     * @return
     */
    private Result passJob(String pid,String jobid,SpcySqsxJob job, String opinion,String nextNodeName,String nextNodeId,String nextNodeDbrIds){
        if (job == null){
            job = spcySqsxJobService.getById(jobid);
        }
        String jobNodeName = job.getFhjmc(); // 当前环节名称

        Result httpResult = null;

        // 指定环节跳转
        if (StringUtils.isNotBlank(nextNodeName)){
            SysFlowNode nowNode = sysFlowNodeService.getNowNodeById(job.getFnodeid());
            if (nowNode != null){
                SysFlowNode zdNode = sysFlowNodeService.getZdNodeByLcmbId(nowNode.getFlcmbid(), nextNodeName);
                nextNodeId = zdNode.getId();
            }
        }

        // 是否为最终结点
        if (StringUtils.isNotBlank(jobNodeName) && (jobNodeName.equals(SpcyFlowConstant.ZLTXWJ_HJMC_END) || jobNodeName.equals(SpcyFlowConstant.ZLTXWJ_HJMC_XGPX_END))){
            //办理掉当前环节
            httpResult = flowNodeService.doJob(job, opinion);
        }else {
            httpResult = flowNodeService.passJob(SpcyFlowConstant.ZLTXWJ_FLOW_CODE, pid, jobid, opinion, nextNodeId, nextNodeDbrIds);
        }

        if (!httpResult.isSuccess()){
            return httpResult;
        }

        return Result.ok("success");
    }

    /**
     * 查询宣贯学习人员姓名列表
     */
    public List<YcSysUser> getXgxxRyxmList(String ids){
        if (StringUtils.isBlank(ids)){
            return new ArrayList<>(1);
        }

        List<String> userIds = StringPatternUtils.getListByIds(ids);
        List<YcSysUser> resultList = new ArrayList<>();

        // 按15为一组进行更新
        List<List<String>> partition = ListUtils.partition(userIds, 30);
        partition.forEach(item -> {
            List<YcSysUser> userList = ycSysUserService.findUserJbxxListByIds(item);
            if (CollectionUtil.isNotEmpty(userList)){
                resultList.addAll(userList);
            }
        });

        return resultList;
    }

    /**
     * 查询宣贯学习人员目录列表
     */
    public List<Map> selectXgxxRymlList(String ids){
        List<Map> resultMapList = new ArrayList<>();
        if (StringUtils.isBlank(ids)){
            return resultMapList;
        }

        List<String> userIds = StringPatternUtils.getListByIds(ids);
        List<YcSysUser> resultList = new ArrayList<>();

        // 按15为一组进行更新
        List<List<String>> partition = ListUtils.partition(userIds, 30);
        partition.forEach(item -> {
            List<YcSysUser> userList = ycSysUserService.findUserJbxxListByIds(item);
            Map dataMap = null;
            for (YcSysUser user : userList){
                dataMap = new HashMap();

                dataMap.put("fuserid", user.getId());
                dataMap.put("realname", user.getRealname());

                resultMapList.add(dataMap);
            }
        });

        return resultMapList;
    }

    /**
     * 发布-宣贯学习-环节流程
     * @param zltxwjid 流程质量体系文件id
     */
    public Result releaseXgxxJob(String zltxwjid, SpcyZltxwjFlow zltxwj, String jobid){
        SpcySqsxJob job = spcySqsxJobService.getById(jobid);
        return releaseXgxxJob(zltxwjid, zltxwj, job);
    }
    public Result releaseXgxxJob(String zltxwjid, SpcyZltxwjFlow zltxwj, SpcySqsxJob nowJob){
        CurrentUserVo currentUser = GetCurrentUserUtils.getCurrentUser();
        if (currentUser == null){
            throw new BusinessException("当前登录已失效，请重新登录！");
        }

        if (StringUtils.isBlank(zltxwjid)){
            log.error("质量体系文件参数为空，请联系管理员！");
            return Result.error("质量体系文件参数为空，请联系管理员！");
        }

        List<SpcySqsxJob> jobList = spcySqsxJobService.selectJobListByFpidInNotOrder(zltxwjid, SpcyFlowConstant.ZLTXWJ_HJMC_XGXX, SpcyFlowConstant.ZLTXWJ_LCMC);
        if (CollectionUtil.isNotEmpty(jobList)){
            return Result.ok("已经生成过了！");
        }

        if (zltxwj == null) {
            zltxwj = spcyZltxwjFlowService.getById(zltxwjid);
            if (zltxwj == null) {
                log.error("前质量体系文件数据不存在，请刷新重试并联系管理员！");
                return Result.error("当前质量体系文件数据不存在，请刷新重试并联系管理员！");
            }
        }

        if (StringUtils.isBlank(zltxwj.getFxgxxryid())){
            log.error("发布失败，请选择并保存宣贯学习所需的人员！");
            return Result.error("发布失败，请选择并保存宣贯学习所需的人员！");
        }

        // 宣贯学习人员
        List<String> userIds = StringPatternUtils.getListByIds(zltxwj.getFxgxxryid());

        // 按15为一组进行更新
        List<List<String>> partition = ListUtils.partition(userIds, 30);
        partition.forEach(item -> {
            List<YcSysUser> userList = ycSysUserService.findUserJbxxListByIds(item);
            for (int i = 0; i < userList.size(); i++) {
                this.initSubJob(zltxwjid, SpcyFlowConstant.ZLTXWJ_HJMC_XGXX,
                        userList.get(i).getId(), userList.get(i).getRealname(),
                        SpcyFlowConstant.DEFAULT_XGXX_OPINION_WXX,
                        currentUser, nowJob);

            }
        });

        return Result.ok("操作成功");
    }

    /**
     * 办结-宣贯学习-环节流程
     */
    public Result completionXgxxJob(String jobid, SpcySqsxJob job, String opinion){
        CurrentUserVo currentUser = GetCurrentUserUtils.getCurrentUser();
        if (currentUser == null){
            return Result.error("当前登录已失效，请重新登录！");
        }
        if (StringUtils.isBlank(jobid)){
            return Result.error("流程任务参数为空，请联系管理员！");
        }
        if (job == null) {
            job = spcySqsxJobService.getById(jobid);
            if (job == null) {
                return Result.error("当前流程任务不存在，请刷新重试并联系管理员！");
            }
        }

        if (StringUtils.isBlank(opinion)){
            opinion = SpcyFlowConstant.DEFAULT_XGXX_OPINION_YXX;
        }
        flowNodeService.doJob(job, opinion);

        return Result.ok();
    }

    /**
     * 发起修订/失效-初始化-质量体系文件流程
     * @param id 质量体系文件id
     * @param isSx 是否失效 (true/false)
     */
    public Result initZltxwjFlow(String id,boolean isSx){
        CurrentUserVo currentUser = GetCurrentUserUtils.getCurrentUser();
        if (currentUser == null){
            return Result.error("当前登录已失效，请重新登录");
        }
        if (StringUtils.isBlank(id)){
            return Result.error("质量体系文件参数不能为空");
        }
        SpcyZltxwjBasic zltxwj = spcyZltxwjBasicService.getById(id);
        if (zltxwj == null){
            return Result.error("质量体系文件不存在，请刷新重试");
        }
        if (StringUtils.isNotBlank(zltxwj.getFxdzt())){
            if (isSx) {
                return Result.error("发起"+SpcyConstant.Zltxwj_Xdlx_SX+"流程失败！,该体系文件正处于【"+zltxwj.getFxdzt()+"】环节！");
            }else {
                return Result.error("发起"+SpcyConstant.Zltxwj_Xdlx_Xd+"流程失败！该体系文件正处于【"+zltxwj.getFxdzt()+"】环节！");
            }
        }

        if (StringUtils.isBlank(zltxwj.getFwjlj())){
            throw new BusinessException("不存在文件！发起失败！");
        }

        // 是否为失效流程
        if (isSx){
            zltxwj.setFxdzt(SpcyConstant.Zltxwj_Xdlx_SX);
        }else {
            zltxwj.setFxdzt(SpcyConstant.Zltxwj_Xdlx_Xd);
        }

        String oldCflj = zltxwj.getFwjlj(); // 旧的文件路径
        String newCflj = "";

        String wjHz = Util.getWjHz(oldCflj);
        String ml = DateConversionUtils.DateToMonthTwo(new Date()); // 获取当前日期 yyyy-MM-dd

        String absOldCflj = "";
        String newWjljMl = "";

        if (businessConstant.isEnableZltxwnjMinio){
            InputStream minioInput = spcyMinioUtils.getObject(oldCflj);
            if (minioInput == null){
                return Result.error("文件流不存在！");
            }
            File file = localFileUploadUtils.asFile(minioInput, wjHz);
            absOldCflj = file.getAbsolutePath();
            newWjljMl = businessConstant.TEMPORARY_UPLOAD_MKDIR_ROOT + "/"+ SpcyConstant.TEMP_WJJL_CHILD_URL;

        }else {
            absOldCflj = businessConstant.UPLOAD_FILE_ROOT + oldCflj;
            newWjljMl = businessConstant.UPLOAD_FILE_ROOT + "/" + SpcyConstant.Flow_Zltxwj_File_Base_Url;
        }

        File dir = new File(newWjljMl + "/" + ml);
        if (!dir.exists()){
            dir.mkdirs();
        }

        String wjccmc = GetUuIdUtils.ReplaceUuId()+wjHz;
        String newWjlj = newWjljMl +"/"+ml+ "/" + wjccmc;
        boolean copyFlag = FileCopyUtils.copyFile(absOldCflj, newWjlj); // 复制文件
        if (copyFlag){
            newCflj = "/" + SpcyConstant.Flow_Zltxwj_File_Base_Url +"/"+ml+ "/" + wjccmc;
        }else {
            throw new BusinessException("初始化复制文件失败！");
        }

        if (businessConstant.isEnableZltxwnjMinio){
            boolean flag = spcyMinioUtils.putFlagFile(newCflj, new File(newWjlj), wjHz);
            if (!flag){
                throw new BusinessException("初始化上传文件失败！");
            }
        }

        LambdaUpdateWrapper<SpcyZltxwjBasic> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(SpcyZltxwjBasic::getId, id);

        SpcyZltxwjBasic updateWj = new SpcyZltxwjBasic();
        updateWj.setFxdzt(zltxwj.getFxdzt());
        spcyZltxwjBasicService.update(updateWj, updateWrapper);

        SpcyZltxwjFlow zltxwjFlow = new SpcyZltxwjFlow(); // 质量体系文件流程
        BeanUtil.copyProperties(zltxwj, zltxwjFlow);
        String flowId = GetUuIdUtils.ReplaceUuId(); // 质量体系文件流程id
        zltxwjFlow.setId(flowId);
        zltxwjFlow.setFsqrid(currentUser.getId());
        zltxwjFlow.setFsqr(currentUser.getName());
        zltxwjFlow.setFsqrq(new Date());
        zltxwjFlow.setFsqks(currentUser.getDeptName());
        zltxwjFlow.setFwjlj(newCflj);
        zltxwjFlow.setFwjlx(wjHz);
        zltxwjFlow.setFpid(id); // 绑定质量体系文件
        if (isSx) {
            zltxwjFlow.setFxglx(SpcyConstant.Zltxwj_Xdlx_SX); // 默认：失效
            zltxwjFlow.setFzt(SpcyConstant.Zltxwj_Zt_Wx); // 失效流程-有效状态-无效
        }else {
            zltxwjFlow.setFxglx(SpcyConstant.Zltxwj_Xdlx_Xd); // 默认：修订
        }

        boolean save = spcyZltxwjFlowService.save(zltxwjFlow);
        if (save) {

            Result result = this.createProcess(flowId, currentUser, false); // 初始化流程
            if (!result.isSuccess()) {
                return Result.error(result.getMessage());
            }else {
                SpcySqsxJob job = (SpcySqsxJob)result.getResult();
                return Result.ok(job);
            }
        }
        return Result.ok("操作成功");
    }

    /**
     * 发起添加-质量体系文件流程
     */
    public Result addInitZltxwjFlow(){
        CurrentUserVo currentUser = GetCurrentUserUtils.getCurrentUser();
        if (currentUser == null){
            return Result.error("当前登录已失效，请重新登录");
        }

        SpcyZltxwjFlow zltxwjFlow = new SpcyZltxwjFlow(); // 质量体系文件流程
        String flowId = GetUuIdUtils.ReplaceUuId(); // 质量体系文件流程id
        zltxwjFlow.setId(flowId);

        // 获取序号
        int total = Optional.ofNullable(spcyZltxwjBasicService.getZltxwjBasicTotal()).orElseGet(()->0);
        int order = total + 1;
        zltxwjFlow.setForder(order);

        zltxwjFlow.setFsqrid(currentUser.getId());
        zltxwjFlow.setFsqr(currentUser.getName());
        zltxwjFlow.setFsqrq(new Date());
        zltxwjFlow.setFscrq(new Date());
        zltxwjFlow.setFsqks(currentUser.getDeptName());
        zltxwjFlow.setFwjlj("");
        zltxwjFlow.setFpid(""); // 绑定质量体系文件
        zltxwjFlow.setFxglx(SpcyConstant.Zltxwj_Xdlx_Xz); // 默认：修订
        zltxwjFlow.setFzt(SpcyConstant.Zltxwj_Zt_Yx); // 有效

        boolean save = spcyZltxwjFlowService.save(zltxwjFlow);
        if (save) {

            Result result = this.createProcess(flowId, currentUser, false); // 初始化流程
            if (!result.isSuccess()) {
                return Result.error(result.getMessage());
            }else {
                SpcySqsxJob job = (SpcySqsxJob)result.getResult();
                return Result.ok(job);
            }
        }

        return Result.ok("初始化成功");
    }

    /**
     * 发起宣贯培训-质量体系文件流程
     * @param txwjids 宣贯文件ids
     * @return job
     */
    public Result xgpxInitZltxwjFlow(String txwjids){
        if (StringUtils.isBlank(txwjids)){
            return Result.error("请选择宣贯文件！");
        }

        CurrentUserVo currentUser = GetCurrentUserUtils.getCurrentUser();
        if (currentUser == null){
            return Result.error("当前登录已失效，请重新登录");
        }

        SpcyZltxwjFlow zltxwjFlow = new SpcyZltxwjFlow(); // 质量体系文件流程
        String flowId = GetUuIdUtils.ReplaceUuId(); // 质量体系文件流程id
        zltxwjFlow.setId(flowId);

        // 获取序号
        int total = Optional.ofNullable(spcyZltxwjBasicService.getZltxwjBasicTotal()).orElseGet(()->0);
        int order = total + 1;
        zltxwjFlow.setForder(order);

        zltxwjFlow.setFsqrid(currentUser.getId());
        zltxwjFlow.setFsqr(currentUser.getName());
        zltxwjFlow.setFsqrq(new Date());
        zltxwjFlow.setFscrq(new Date());
        zltxwjFlow.setFsqks(currentUser.getDeptName());
        zltxwjFlow.setFxglx(SpcyConstant.Zltxwj_Xdlx_XGPX); // 默认：修订
        zltxwjFlow.setFzt(SpcyConstant.Zltxwj_Zt_Yx); // 有效

        boolean save = spcyZltxwjFlowService.save(zltxwjFlow);
        if (save) {

            Result result = this.createProcess(flowId, currentUser, false); // 初始化流程
            if (!result.isSuccess()) {
                return Result.error(result.getMessage());
            }else {
                SpcySqsxJob job = (SpcySqsxJob)result.getResult();

                List<SpcyZltxwjXgpxwj> xgpxwjList = new ArrayList<>();
                for (String txwjid : StringPatternUtils.getListByIds(txwjids)){
                    SpcyZltxwjXgpxwj xgpxwj = new SpcyZltxwjXgpxwj();
                    xgpxwj.setId(GetUuIdUtils.ReplaceUuId());
                    xgpxwj.setFpid(zltxwjFlow.getId());
                    xgpxwj.setFtxwjid(txwjid);

                    xgpxwjList.add(xgpxwj);
                }
                spcyZltxwjXgpxwjService.saveBatch(xgpxwjList);
                return Result.ok(job);
            }
        }

        return Result.ok("初始化成功");
    }

    /**
     * 查询当前选中的体系文件列表
     */
    public HttpResult selectNowSztxwjList(String txwjids){
        if (StringUtils.isBlank(txwjids)){
            return HttpResult.error("请选择宣贯文件！");
        }

        return HttpResultVo.HttpResultList(spcyZltxwjBasicService.listByIds(StringPatternUtils.getListByIds(txwjids)));
    }

    /**
     * 初始化宣贯培训人员的文件记录
     */
    public Result initXgpxwjWithXfxxryIds(String fxdlx, String fpid, String fxgxxryid){
        if (StringUtils.isBlank(fxdlx) || !fxdlx.equals(SpcyConstant.Zltxwj_Xdlx_XGPX)){
            return Result.ok();
        }

        // 未初始化宣贯文件列表
        List<SpcyZltxwjXgpxwj> orgXgwjList = spcyZltxwjXgpxwjService.list(new LambdaQueryWrapper<SpcyZltxwjXgpxwj>()
                .eq(SpcyZltxwjXgpxwj::getFpid, fpid)
                .isNull(SpcyZltxwjXgpxwj::getFuserid));

        // 宣贯学习人员
        List<YcSysUser> xgxxryList = ycSysUserService.findRealnameListByIds(StringPatternUtils.getListByIds(fxgxxryid));
        List<SpcyZltxwjXgpxwj> newXgpxwjList = null;
        for (YcSysUser user : xgxxryList){
            newXgpxwjList = new ArrayList<>(orgXgwjList.size());
            SpcyZltxwjXgpxwj newXgpxwj = null;
            for (SpcyZltxwjXgpxwj orgXgwj : orgXgwjList){
                newXgpxwj = new SpcyZltxwjXgpxwj();

                BeanUtil.copyProperties(orgXgwj, newXgpxwj);
                newXgpxwj.setId(GetUuIdUtils.ReplaceUuId());
                newXgpxwj.setFuserid(user.getId());
                newXgpxwj.setFxm(user.getRealname());

                newXgpxwjList.add(newXgpxwj);
            }
            spcyZltxwjXgpxwjService.saveBatch(newXgpxwjList);
        }

        // 删除原始文件记录
        /*spcyZltxwjXgpxwjService.remove(new LambdaQueryWrapper<SpcyZltxwjXgpxwj>()
                .eq(SpcyZltxwjXgpxwj::getFpid, fpid)
                .isNull(SpcyZltxwjXgpxwj::getFuserid));*/

        return Result.ok();
    }

    /**
     * 查询宣贯培训文件详情列表
     * */
    public List<ZltxwjXgwjVo> selectXgpxwjInfo(String fpid, String fuserid){
        return this.selectXgpxwjInfo(fpid, fuserid, "", null);
    }
    public List<ZltxwjXgwjVo> selectXgpxwjInfo(String fpid, String fuserid, String realname, SpcySqsxJob job){

        // 宣贯文件列表
        List<SpcyZltxwjXgpxwj> orgXgwjList = null;
        List<SpcyZltxwjBasic> orgTxwjList = null;
        if (StringUtils.isBlank(fuserid)){
            orgXgwjList = spcyZltxwjXgpxwjService.list(new LambdaQueryWrapper<SpcyZltxwjXgpxwj>()
                    .eq(SpcyZltxwjXgpxwj::getFpid, fpid)
                    .isNull(SpcyZltxwjXgpxwj::getFuserid));

            orgTxwjList = spcyZltxwjXgpxwjService.selectTxwjBaseListByFpidAndNullUserid(fpid);

        }else {
            orgXgwjList = spcyZltxwjXgpxwjService.list(new LambdaQueryWrapper<SpcyZltxwjXgpxwj>()
                    .eq(SpcyZltxwjXgpxwj::getFpid, fpid)
                    .eq(SpcyZltxwjXgpxwj::getFuserid, fuserid));

            orgTxwjList = spcyZltxwjXgpxwjService.selectTxwjBaseListByFpidAndFuserid(fpid, fuserid);
        }

        List<ZltxwjXgwjVo> dataMapList = new ArrayList<>(orgXgwjList.size());
        for (SpcyZltxwjXgpxwj orgXgwj : orgXgwjList){

            // 重构文件id
            SpcyZltxwjBasic txwj = orgTxwjList.stream()
                    .filter(f -> f.getId().equals(orgXgwj.getFtxwjid()))
                    .collect(Collectors.toList())
                    .get(0);
            txwj.setId(orgXgwj.getId());
            txwj.setFwjlj("");
            txwj.setFpdfurl("");
            ZltxwjXgwjVo xgwjVo = new ZltxwjXgwjVo();
            BeanUtil.copyProperties(txwj, xgwjVo);
            xgwjVo.setFxxyj(orgXgwj.getFxxyj());
            xgwjVo.setRealname(realname);

            if (job != null){
                xgwjVo.setFblsj(job.getFblsj());
                xgwjVo.setFblzt(job.getFblzt());
                xgwjVo.setFblyj(job.getFblyj());
            }
            dataMapList.add(xgwjVo);
        }

         return dataMapList;
    }

    /** 更新宣贯文件-学习意见 */
    public HttpResult updateXgwjXxyjById(SpcyZltxwjXgpxwj bean){
        if (StringUtils.isBlank(bean.getId())){
            return HttpResult.error("参数为空！");
        }

        LambdaUpdateWrapper<SpcyZltxwjXgpxwj> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(SpcyZltxwjXgpxwj::getId, bean.getId());

        SpcyZltxwjXgpxwj updateBean = new SpcyZltxwjXgpxwj();
        updateBean.setFxxyj(Optional.ofNullable(bean.getFxxyj()).orElse(""));
        spcyZltxwjXgpxwjService.update(updateBean, updateWrapper);

        return HttpResult.ok("保存成功");
    }

    /**
     * 勾选新增宣贯培训文件记录
     */
    public HttpResult selectAddXgpxwj(String fpid, String ids){
        if (StringUtils.isBlank(fpid)){
            return HttpResult.error("业务参数为空！");
        }
        if (StringUtils.isBlank(ids)){
            return HttpResult.error("请选择文件！");
        }
        List<SpcyZltxwjXgpxwj> xgpxwjList = new ArrayList<>();
        for (String txwjid : StringPatternUtils.getListByIds(ids)){
            SpcyZltxwjXgpxwj xgpxwj = new SpcyZltxwjXgpxwj();
            xgpxwj.setId(GetUuIdUtils.ReplaceUuId());
            xgpxwj.setFpid(fpid);
            xgpxwj.setFtxwjid(txwjid);

            xgpxwjList.add(xgpxwj);
        }
        spcyZltxwjXgpxwjService.saveBatch(xgpxwjList);

        return HttpResult.ok("操作成功");
    }

    /**
     * 删除宣贯培训文件记录
     */
    public Result deleteXgpxwjList(String id, String fxdlx, String fpid){
        if (StringUtils.isNotBlank(id)){
            spcyZltxwjXgpxwjService.removeById(id);
        }else {
            if (StringUtils.isBlank(fxdlx) || !fxdlx.equals(SpcyConstant.Zltxwj_Xdlx_XGPX)) {
                return Result.ok();
            }

            spcyZltxwjXgpxwjService.remove(new LambdaQueryWrapper<SpcyZltxwjXgpxwj>()
                    .eq(SpcyZltxwjXgpxwj::getFpid, fpid));
        }

        return Result.ok();
    }

    /**
     * 删除-质量体系文件流程
     * @param zltxwjid 质量体系文件id
     */
    public Result deleteZltxwjFlow(String zltxwjid){
        if (StringUtils.isBlank(zltxwjid)){
            return Result.error("质量体系文件id不能为空");
        }
        SpcyZltxwjFlow zltxwj = spcyZltxwjFlowService.getById(zltxwjid);
        if (zltxwj == null){
            return Result.error("当前质量体系文件流程记录不存在，请刷新重试");
        }
        if (StringUtils.isNotBlank(zltxwj.getFpid())) {
            SpcyZltxwjBasic zltxwjBasic = spcyZltxwjBasicService.getById(zltxwj.getFpid());
            if (zltxwjBasic != null) {
                zltxwjBasic.setFxdzt("");
                spcyZltxwjBasicService.updateById(zltxwjBasic);
            }
        }

        spcyZltxwjFlowService.removeById(zltxwjid);
        if (StringUtils.isNotBlank(zltxwj.getFwjlj())){
            localFileUploadUtils.deleteLocalFileUrlByZltxwj(zltxwj.getFwjlj());
            if (StringUtils.isNotBlank(zltxwj.getFjdwjlj())){
                localFileUploadUtils.deleteLocalFileUrlByZltxwj(zltxwj.getFjdwjlj());
            }
        }

        spcySqsxJobService.remove(new LambdaQueryWrapper<SpcySqsxJob>().eq(SpcySqsxJob::getFpid, zltxwjid));

        // 删除宣贯培训文件
        this.deleteXgpxwjList(null, zltxwj.getFxglx(), zltxwjid);

        String operContent = "删除质量体系文件流程信息：";
        Map<String, Object> oldMap = ObjectToMapUtils.objectToMap(zltxwj);
        operContent += LogUtils.MapToStringMethod(oldMap);
        spcyLogService.addLogs(LogConstant.LOGS_ZLTXWJ,operContent,zltxwjid,"删除质量体系文件流程",SpcyConstant.LOGS_SYS_TYPE_SC);

        return Result.ok("操作成功");
    }

    /**
     * 初始化-指定环节-子流程环节
     * @param pid 流程申请id
     * @param nextNodeName 指定环节
     * @param nextNodeDbrIds 环节待办人id
     * @param nextNodeDbrs 环节待办人
     * @param opinion 意见
     * @param currentUser 当前登录人
     * @return
     */
    public Result initSubJob(String pid, String nextNodeName,String nextNodeDbrIds,String nextNodeDbrs,String opinion,CurrentUserVo currentUser,SpcySqsxJob nowJob){
        if (StringUtils.isBlank(nextNodeName)){
            return Result.error("环节参数为空！");
        }

        if (StringUtils.isBlank(nextNodeDbrIds)){
            return Result.error("待办人参数为空！");
        }

        if (StringUtils.isBlank(nextNodeDbrs)){
            return Result.error("待办人名称参数为空！");
        }

        SpcySqsxJob job = new SpcySqsxJob();
        job.setId(GetUuIdUtils.ReplaceUuId());
        job.setFpid(pid);
        job.setFhjmc(nextNodeName);
        if (currentUser != null) {
            job.setFfsrid(currentUser.getId());
            job.setFfsrmc(currentUser.getName());
        }
        if (StringUtils.isNotBlank(opinion)){
            job.setFblyj(opinion);
        }
        job.setFfssj(new Date());

        job.setFdbrid(nextNodeDbrIds);
        job.setFdbr(nextNodeDbrs);
        job.setFydbrid(nextNodeDbrIds);
        job.setFydbr(nextNodeDbrs);
        job.setFblzt(SpcyConstant.BLZT_DB);

        if (nowJob != null) {
            job.setFlcmc(nowJob.getFlcmc());
            job.setFsyhjid(nowJob.getId());
        }else {
            job.setFlcmc(SpcyFlowConstant.ZLTXWJ_LCMC);
            job.setFsyhjid("");
        }
        job.setFblfs(FlowNodeConstant.BLFS_DRJJ);

        spcySqsxJobService.save(job);

        return Result.ok(job);
    }

    /**
      * 退回流程
     */
    public void getReturnUpperFlowJob(SpcyReturnVo spcyReturnVo){
        CurrentUserVo currentUser = GetCurrentUserUtils.getCurrentUser();
        if (currentUser == null){
            throw new BusinessException("登录已失效，请重新登录！");
        }

        if (StringUtils.isBlank(spcyReturnVo.getJobid())){
            throw new BusinessException("流程任务参数为空！");
        }

        if (StringUtils.isBlank(spcyReturnVo.getOpinion())){
            throw new BusinessException("请填写退回意见！");
        }

        SpcySqsxJob currentJob = spcySqsxJobService.getById(spcyReturnVo.getJobid());
        if (currentJob == null){
            throw new BusinessException("退回失败！当前流程任务不存在！");
        }

        SpcySqsxJob previousJob = getCurrentJobPrevious(spcyReturnVo.getJobid(), currentJob);
        if (previousJob == null){
            throw new BusinessException("["+currentJob.getFhjmc()+"]退回失败！退回环节不存在！");
        }

        // 退回功能
        Result result = flowNodeService.returnJob(spcyReturnVo.getJobid(), currentJob, spcyReturnVo.getShjid(), previousJob, spcyReturnVo.getOpinion(), currentUser);
        if (result.isSuccess()){

            if (StringUtils.isNotBlank(spcyReturnVo.getSmgflag()) && (spcyReturnVo.getSmgflag().equals("是") || spcyReturnVo.getSmgflag().equals("true"))) {
                SpcySqsxJob newPreviousJob = (SpcySqsxJob) result.getResult();
                // 发送退回短信
                String nextNodeSmsContent = busService.getNextNodeSmsContent(newPreviousJob, null);
                busService.sendNextNodeSmsContent(newPreviousJob, nextNodeSmsContent);
            }
        }
    }

    /**
     * 查询审评查验流程当前环节-上一环节
     * @param jobid 流程任务id
     * @return
     */
    private SpcySqsxJob getCurrentJobPrevious(String jobid, SpcySqsxJob nowJob){
        if (StringUtils.isBlank(jobid)){
            throw new BusinessException("流程任务参数为空！");
        }
        SpcySqsxJob previousJob = null;

        if (nowJob == null) {
            nowJob = spcySqsxJobService.getById(jobid);
            if (nowJob == null) {
                throw new BusinessException("当前流程任务不存在！");
            }
        }

        if (StringUtils.isBlank(nowJob.getFnodeid())){
            throw new BusinessException("当前流程任务结点配置不存在！");
        }

        // 当前环节的上一个环节id
        List<SysFlowNode> previousNodeList = sysFlowNodeService.getPreviousNode(nowJob.getFnodeid());
        if (CollectionUtil.isEmpty(previousNodeList)){
            return previousJob;
        }

        LambdaQueryWrapper<SpcySqsxJob> queryWrapper = this.genGetCurrentJobPreviousWrapper(nowJob.getFpid(), previousNodeList);
        // 上环节结点id-办理过的流程任务
        List<SpcySqsxJob> previousJobList = spcySqsxJobService.list(queryWrapper);
        if (CollectionUtil.isEmpty(previousJobList)){
            /*// 当前环节的上一个环节id的上一个环节id
            previousNodeList = sysFlowNodeService.getPreviousNode(previousNodeList.get(0).getId());
            if (CollectionUtil.isEmpty(previousNodeList)){
                return previousJob;
            }

            LambdaQueryWrapper<SpcySqsxJob> queryWrapper2 = this.genGetCurrentJobPreviousWrapper(nowJob.getFpid(), previousNodeList);

            // 上环节结点id-办理过的流程任务
            previousJobList = spcySqsxJobService.list(queryWrapper2);*/

            /*if (CollectionUtil.isEmpty(previousJobList)){
                // 当前环节的上一个环节id的上一个环节id
                previousNodeList = sysFlowNodeService.getPreviousNode(previousNodeList.get(0).getId());
                if (CollectionUtil.isEmpty(previousNodeList)){
                    return previousJob;
                }

                LambdaQueryWrapper<SpcySqsxJob> queryWrapper3 = this.genGetCurrentJobPreviousWrapper(nowJob.getFpid(), previousNodeList);
                previousJobList = spcySqsxJobService.list(queryWrapper3);
            }*/

            previousJobList = this.previousJobListDg(previousJobList, previousNodeList, nowJob);
        }

        if (CollectionUtil.isNotEmpty(previousJobList)) {
            for (int i = 0; i < previousJobList.size(); i++) {
                previousJob = previousJobList.get(0);
            }
        }

        return previousJob;
    }

    // 递归获取上一个环节
    private List<SpcySqsxJob> previousJobListDg(List<SpcySqsxJob> previousJobList, List<SysFlowNode> previousNodeList, SpcySqsxJob nowJob){
        // 当前环节的上一个环节id的上一个环节id
        previousNodeList = sysFlowNodeService.getPreviousNode(previousNodeList.get(0).getId());
        if (CollectionUtil.isEmpty(previousNodeList)){
            return null;
        }

        LambdaQueryWrapper<SpcySqsxJob> queryWrapper3 = this.genGetCurrentJobPreviousWrapper(nowJob.getFpid(), previousNodeList);
        previousJobList = spcySqsxJobService.list(queryWrapper3);
        if (CollectionUtil.isEmpty(previousJobList)){
            return this.previousJobListDg(previousJobList, previousNodeList, nowJob);
        }

        return previousJobList;
    }

    /** 构建上一个环节流程查询条件 */
    private LambdaQueryWrapper<SpcySqsxJob> genGetCurrentJobPreviousWrapper(String pid, List<SysFlowNode> previousNodeList){
        LambdaQueryWrapper<SpcySqsxJob> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SpcySqsxJob::getFpid, pid);
        queryWrapper.orderByAsc(SpcySqsxJob::getFfssj);

        if (previousNodeList.size() == 1) {
            queryWrapper.eq(SpcySqsxJob::getFnodeid, previousNodeList.get(0).getId());
        }else {
            List<String> preIdsList = previousNodeList.stream().map(SysFlowNode::getId).collect(Collectors.toList());
            queryWrapper.in(SpcySqsxJob::getFnodeid, preIdsList);
        }

        return queryWrapper;
    }

    /**
     * 获取当前流程任务相关信息
     * @param jobid 流程任务id
     */
    public Map getJobConcernByJobId(String jobid){
        Map map = new HashMap();

        // 当前流转记录
        SpcySqsxJob job = spcySqsxJobService.getById(jobid);
        if (job == null){
            log.error("当前流程任务id为【{}】的流转记录不存在",jobid);
            return map;
        }

        String zltxwjid = job.getFpid();
        if (org.apache.commons.lang3.StringUtils.isBlank(zltxwjid)){
            log.error("当前流程任务id为【{}】的流转记录中的质量体系文件id为空",jobid);
            return map;
        }

        SpcyZltxwjFlow zltxwj = spcyZltxwjFlowService.getById(zltxwjid);
        if (zltxwj == null){
            log.error("当前流程任务id为【{}】的流转记录中的质量体系文件id{}为空",jobid,zltxwjid);
            return map;
        }

        map.put("zltxwj",zltxwj); // 质量体系文件基本信息
        map.put("job",job); // 当前流转记录

        // 获取下环节待办人
        try {
            map.putAll(this.getNextNodeDbr(jobid, job, zltxwj));
        }catch (Exception e){
            log.error(e.getMessage());
        }

        return map;
    }

    /**
     * 获取申请事项-流转记录
     */
    public List<SpcySqsxJob> getJobListBySqsxId(String sqid){
        /*LambdaQueryWrapper<SpcySqsxJob> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SpcySqsxJob::getFpid, sqid);
        queryWrapper.like(SpcySqsxJob::getFlcmc, SpcyFlowConstant.ZLTXWJ_LCMC);
        queryWrapper.orderByAsc(SpcySqsxJob::getFfssj);
        queryWrapper.orderByAsc(SpcySqsxJob::getCreateTime);
        List<SpcySqsxJob> jobList = spcySqsxJobService.list(queryWrapper);*/

        List<SpcySqsxJob> jobList = spcySqsxJobService.selectJobListByFpidInOrder(sqid, SpcyFlowConstant.ZLTXWJ_LCMC);

        return jobList;
    }

    /**
     * 获取下环节待办人
     * @param jobid
     * @param job
     * @return
     */
    private Map getNextNodeDbr(String jobid,SpcySqsxJob job, SpcyZltxwjFlow zltxwjFlow){
        Map map = new HashMap();

        Map nextDbr = this.getNowJobInNextDbrAndHandlePageUrl(jobid, job);
        String nextNodeId = ""; // 下结点id
        String nextNode = "办结"; // 下结点名称
        if (nextDbr.get("nextNode") != null) {
            SysFlowNode nextFlowNode = (SysFlowNode) nextDbr.get("nextNode");
            nextNodeId = nextFlowNode.getId();
            nextNode = nextFlowNode.getFjdmc();
        }
        List<AgentVo> dbrListByMap = this.getDbrListByMap(nextDbr);

        if (zltxwjFlow != null && zltxwjFlow.getFxglx().equals(SpcyConstant.Zltxwj_Xdlx_XGPX)){

            if (job.getFhjmc().equals(SpcyFlowConstant.ZLTXWJ_HJMC_KSFH)){
                nextNode = SpcyFlowConstant.ZLTXWJ_HJMC_XGXX + "/" + SpcyFlowConstant.ZLTXWJ_HJMC_XGXGPJ;
                nextNodeId = nextNode;

                Map dbrMap = getzltxwjfzrByDeptName(SpcyConstant.DEPT_NAME_ZHYWK);
                dbrListByMap = this.getDbrListByMap(dbrMap);

            }else if (job.getFhjmc().equals(SpcyFlowConstant.ZLTXWJ_HJMC_XGXGPJ)){
                nextNode = SpcyFlowConstant.ZLTXWJ_HJMC_WJSS;
                nextNodeId = nextNode;

                Map dbrMap = getKsfzrByDeptName(SpcyConstant.DEPT_NAME_ZHYWK);
                dbrListByMap = this.getDbrListByMap(dbrMap);
            }

        }

        if (!zltxwjFlow.getFxglx().equals(SpcyConstant.Zltxwj_Xdlx_XGPX)) {
            // 跳环节
            if (job.getFhjmc().equals(SpcyFlowConstant.ZLTXWJ_HJMC_KSFH) && StringUtils.isNotBlank(zltxwjFlow.getFsqks())) {
                boolean flag = false;
                if (zltxwjFlow.getFsqks().equals(SpcyConstant.YPSC_ORG_NAME)) {
                    nextNode = SpcyFlowConstant.ZLTXWJ_HJMC_GLZDB;
                    flag = true;
                } else if (zltxwjFlow.getFsqks().equals(SpcyConstant.YPZC_ORG_NAME)) {
                    nextNode = SpcyFlowConstant.ZLTXWJ_HJMC_GLZDB;
                    flag = true;
                }

                if (flag) {
                    nextNodeId = nextNode;

                    Map dbrMap = getGlzdb();
                    dbrListByMap = this.getDbrListByMap(dbrMap);
                }
            }
        }

        // 中心领导跳环节（修订类型）
        if (job.getFhjmc().equals(SpcyFlowConstant.ZLTXWJ_HJMC_ZXLD)){

            if (StringUtils.isNotBlank(zltxwjFlow.getFxglx())){
                if (zltxwjFlow.getFxglx().equals(SpcyConstant.Zltxwj_Xdlx_Xz)){
                    nextNode = SpcyConstant.Zltxwj_Xdlx_Xz + SpcyFlowConstant.ZLTXWJ_HJMC_SH_BAK;
                }else if (zltxwjFlow.getFxglx().equals(SpcyConstant.Zltxwj_Xdlx_SX)){
                    nextNode = SpcyConstant.Zltxwj_Xdlx_SX + SpcyFlowConstant.ZLTXWJ_HJMC_SH_BAK;
                }else {
                    nextNode = SpcyFlowConstant.ZLTXWJ_HJMC_XDSH;
                }
            }else {
                nextNode = SpcyFlowConstant.ZLTXWJ_HJMC_XDSH;
            }

            nextNodeId = nextNode;

            // 质量管理与科研科-科室负责人
            Map dbrMap = getKsfzrByDeptName(SpcyConstant.DEPT_NAME_ZHYWK);
            dbrListByMap = this.getDbrListByMap(dbrMap);
        }

        if (job.getFhjmc().equals(SpcyFlowConstant.ZLTXWJ_HJMC_FGLD)){

            // 验证当前待办人与下一个环节待办人是否相同
            VerifyNowNextJobDbrVo dbrVo = this.verifyNextAndNowJobDbrSfxt(dbrListByMap, job, SpcyFlowConstant.ZLTXWJ_HJMC_GLZDB);
            if (dbrVo != null){
                nextNode = dbrVo.getNextNode();
                nextNodeId = dbrVo.getNextNodeId();
                dbrListByMap = dbrVo.getDbrListByMap();
            }
        }

        map.put("nextNode", nextNode); // 下流程结点名称
        map.put("nextNodeId", nextNodeId); // 下流程结点id
        map.put("nextNodeDbrList", dbrListByMap); // 下环节待办人list

        return map;
    }

    /** 验证当前待办人与下一个环节待办人是否相同 */
    private VerifyNowNextJobDbrVo verifyNextAndNowJobDbrSfxt(List<AgentVo> dbrListByMap, SpcySqsxJob nowJob, String nextNode){
        if (CollectionUtil.isNotEmpty(dbrListByMap) && dbrListByMap.size() == 1){
            if (StringUtils.isNotEmpty(dbrListByMap.get(0).getDbrid())
                    && StringUtils.isNotBlank(nowJob.getFdbrid())
                    && dbrListByMap.get(0).getDbrid().contains(nowJob.getFdbrid())){

                VerifyNowNextJobDbrVo dbrVo = new VerifyNowNextJobDbrVo();

                if (nextNode.equals(SpcyFlowConstant.ZLTXWJ_HJMC_GLZDB)){
                    dbrVo.setNextNode(SpcyFlowConstant.ZLTXWJ_HJMC_ZXLD);
                    dbrVo.setNextNodeId(dbrVo.getNextNode());
                }else {
                    dbrVo.setNextNode(nextNode);
                    dbrVo.setNextNodeId(nextNode);
                }

                // 中心领导
                Map dbrMap = null;
                if (dbrVo.getNextNode().equals(SpcyFlowConstant.ZLTXWJ_HJMC_ZXLD)) {
                    dbrMap = getZxld();
                    dbrListByMap = this.getDbrListByMap(dbrMap);

                }else if (dbrVo.getNextNode().equals(SpcyFlowConstant.ZLTXWJ_HJMC_GLZDB)){
                    dbrMap = getGlzdb();
                    dbrListByMap = this.getDbrListByMap(dbrMap);

                }

                if (CollectionUtil.isEmpty(dbrListByMap)) {
                    dbrVo.setErrorMsg(nextNode+"办理人为空！");
                }else {
                    if (dbrMap != null) {
                        dbrVo.setNextNodeDbrId(dbrMap.get("dbrId").toString());
                    }
                    dbrVo.setDbrListByMap(dbrListByMap);
                }

                return dbrVo;
            }
        }

        return null;
    }

    /**
     * 获取下一个环节名称和待办人
     * @param job 流程任务
     * @param jobid 流程任务id
     * @return
     * {
     *     dbrId
     *     dbr:
     *     nextNode：下流程结点
     *     handlePageUrl：办理页面路径
     * }
     */
    private Map getNowJobInNextDbrAndHandlePageUrl(String jobid, SpcySqsxJob job){
        if (job == null && StringUtils.isNotBlank(jobid)){
            job = spcySqsxJobService.getById(jobid);
        }
        String flowCode = SpcyFlowConstant.ZLTXWJ_FLOW_CODE;
        return flowNodeService.getNowJobInNextDbrAndHandlePageUrl(flowCode, job, null);
    }

    /** 获取当前环节待办人 */
    public Map getNodeDbr(String pid,String nodeName){
        Map map = new HashMap();
        String dbrId = "";
        String dbr = "";

        String deptName = "";
        SpcyZltxwjFlow zltxwj = spcyZltxwjFlowService.getById(pid);
        if (zltxwj != null){
            deptName = zltxwj.getFsqks();
        }

        // 申请
        if (nodeName.equals(SpcyFlowConstant.ZLTXWJ_HJMC_SQ)){
            if (zltxwj != null) {
                dbrId = zltxwj.getFsqrid();
                dbr = zltxwj.getFsqr();
            }
        }

        // 科室复核
        if (nodeName.equals(SpcyFlowConstant.ZLTXWJ_HJMC_KSFH)){
            // 科室负责人
            Map kzMap = getKsfzrByDeptName(deptName);
            dbrId = kzMap.get("dbrId").toString();
            dbr = kzMap.get("dbr").toString();
        }


        // 分管领导
        if (nodeName.equals(SpcyFlowConstant.ZLTXWJ_HJMC_FGLD)) {
            Map kzMap = null;

            if (deptName.contains(SpcyConstant.YWFL_NAME_YPSC)){
                kzMap = getGlzdb();

            } else if (deptName.contains(SpcyConstant.YWFL_NAME_YLQX)){
                kzMap = getGlzdb();

            } else {
                kzMap = getKsFgldByDeptName(deptName);
            }
            // 分管领导
            dbrId = kzMap.get("dbrId").toString();
            dbr = kzMap.get("dbr").toString();
        }

        // 质量负责人
        if (nodeName.equals(SpcyFlowConstant.ZLTXWJ_HJMC_GLZDB)) {
            Map kzMap = getGlzdb();
            dbrId = kzMap.get("dbrId").toString();
            dbr = kzMap.get("dbr").toString();
        }

        // 中心领导
        if (nodeName.equals(SpcyFlowConstant.ZLTXWJ_HJMC_ZXLD)) {
            // 中心领导（蒋受军）药品生产分管领导
            Map kzMap = getZxld();
            dbrId = kzMap.get("dbrId").toString();
            dbr = kzMap.get("dbr").toString();
        }

        // 修订确认
        if (nodeName.equals(SpcyFlowConstant.ZLTXWJ_HJMC_XDQR)) {
            // 质量管理与科研科-质量体系文件负责人
            Map kzMap = getzltxwjfzrByDeptName(SpcyConstant.DEPT_NAME_ZHYWK);
            dbrId = kzMap.get("dbrId").toString();
            dbr = kzMap.get("dbr").toString();
        }

        // 修订审核
        if (nodeName.equals(SpcyFlowConstant.ZLTXWJ_HJMC_XDSH)){
            // 质量管理与科研科-科室负责人
            Map kzMap = getKsfzrByDeptName(SpcyConstant.DEPT_NAME_ZHYWK);
            dbrId = kzMap.get("dbrId").toString();
            dbr = kzMap.get("dbr").toString();
        }

        // 宣贯效果评价
        if (nodeName.equals(SpcyFlowConstant.ZLTXWJ_HJMC_XGXGPJ)){
            // 质量管理与科研科-质量体系文件负责人
            Map kzMap = getzltxwjfzrByDeptName(SpcyConstant.DEPT_NAME_ZHYWK);
            dbrId = kzMap.get("dbrId").toString();
            dbr = kzMap.get("dbr").toString();
        }

        // 实施发布
        if (nodeName.equals(SpcyFlowConstant.ZLTXWJ_HJMC_SSFB)){
            // 质量管理与科研科-科室负责人
            Map kzMap = getKsfzrByDeptName(SpcyConstant.DEPT_NAME_ZHYWK);
            dbrId = kzMap.get("dbrId").toString();
            dbr = kzMap.get("dbr").toString();
        }

        // 文件实施
        if (nodeName.equals(SpcyFlowConstant.ZLTXWJ_HJMC_WJSS)){
            // 质量管理与科研科-科室负责人
            Map kzMap = getKsfzrByDeptName(SpcyConstant.DEPT_NAME_ZHYWK);
            dbrId = kzMap.get("dbrId").toString();
            dbr = kzMap.get("dbr").toString();
        }

        map.put("dbrId",dbrId);
        map.put("dbr",dbr);
        return map;
    }

    /** 对应科室的 科室负责人 */
    public Map getKsfzrByDeptName(String deptName){
        Map map = new HashMap();
        String dbrId = "";
        String dbr = "";
        List<GetKsKz> ksKzObject = new ArrayList<>();
        ksKzObject = ycSysUserService.getKsKzObject(deptName, SpcyConstant.GW_NAME_KZ);
        if (CollectionUtils.isNotEmpty(ksKzObject)) {
            for (GetKsKz ksKz : ksKzObject) {
                dbrId += ksKz.getId() +",";
                dbr += ksKz.getRealname() +",";
            }
        }

        map.put("dbrId",dbrId);
        map.put("dbr",dbr);
        return map;
    }

    /** 获取对应科室的 分管领导 */
    public Map getKsFgldByDeptName(String deptName){
        Map map = new HashMap();
        String dbrId = "";
        String dbr = "";

        YcSysUser fgldUserBydept = sysUserFgldService.getFgldUserBydept(deptName);
        if (fgldUserBydept != null) {
            dbrId = fgldUserBydept.getId();
            dbr = fgldUserBydept.getRealname();
        }

        map.put("dbrId",dbrId);
        map.put("dbr",dbr);
        return map;
    }

    /** 中心领导 */
    public Map getZxld(){
        Map map = new HashMap();
        String dbrId = "";
        String dbr = "";
        List<GetKsKz> ksKzObject = new ArrayList<>();
        ksKzObject = ycSysUserService.getKsKzObject("", SpcyConstant.GW_ZXLD);

        if (CollectionUtils.isNotEmpty(ksKzObject)) {
            for (GetKsKz ksKz : ksKzObject) {
                dbrId += ksKz.getId()+",";
                dbr += ksKz.getRealname()+",";
            }
        }

        map.put("dbrId",dbrId);
        map.put("dbr",dbr);
        return map;
    }

    /** 质量负责人 */
    public Map getGlzdb(){
        Map map = new HashMap();
        String dbrId = "";
        String dbr = "";
        List<GetKsKz> ksKzObject = new ArrayList<>();
        ksKzObject = ycSysUserService.getKsKzObject("", SpcyConstant.GW_ZLFZR);

        if (CollectionUtils.isNotEmpty(ksKzObject)) {
            for (GetKsKz ksKz : ksKzObject) {
                dbrId += ksKz.getId()+",";
                dbr += ksKz.getRealname()+",";
            }
        }

        map.put("dbrId",dbrId);
        map.put("dbr",dbr);
        return map;
    }

    /** 对应科室的 质量体系文件负责人 */
    public Map getzltxwjfzrByDeptName(String deptName){
        Map map = new HashMap();
        String dbrId = "";
        String dbr = "";
        List<GetKsKz> ksKzObject = new ArrayList<>();
        ksKzObject = ycSysUserService.getKsKzObject(deptName, SpcyConstant.GW_ZLTXWJ_FZR);

        if (CollectionUtils.isNotEmpty(ksKzObject)) {
            for (GetKsKz ksKz : ksKzObject) {
                dbrId += ksKz.getId()+",";
                dbr += ksKz.getRealname()+",";
            }
        }

        map.put("dbrId",dbrId);
        map.put("dbr",dbr);
        return map;
    }

    /**
     * 将待办人map转为List
     * @param map { dbrId: 待办人id ; dbr: 待办人 }
     */
    private List<AgentVo> getDbrListByMap(Map map){
        String dbrids = map.get("dbrId").toString(); // 待办人id
        String dbrs = map.get("dbr").toString(); // 待办人

        List<AgentVo> agentList = new ArrayList<>();

        if (StringUtils.isNotBlank(dbrids)) {
            String agentIds[] = dbrids.split(",|，");
            String agentNames[] = dbrs.split(",|，");

            for (int i = 0; i < agentIds.length; i++) {
                AgentVo agentVo = new AgentVo();
                agentVo.setDbrid(agentIds[i]);
                agentVo.setDbr(agentNames[i]);
                agentList.add(agentVo);
            }
        }

        return agentList;
    }

    /**
     * 更新基本信息
     */
    public Result updateJbxx(HashMap<String,Object> map,String ywid,SpcySqsxJob job){
        if (map == null || map.isEmpty()){
            return Result.ok();
        }
        SpcyZltxwjFlow basicUpdate = spcyZltxwjFlowService.getById(ywid);
        if (basicUpdate == null){
            return Result.error("当前质量体系文件【"+ywid+"】不存在，请重试");
        }
        SpcyZltxwjFlow oldBean = basicUpdate;

        // 修改
        ConvertUtils.register(new DateConvert(), java.util.Date.class);
        try {
            BeanUtils.populate(basicUpdate,map);

            if (StringUtils.isBlank(oldBean.getFtypeid())) {
                if (StringUtils.isNotBlank(basicUpdate.getFtypeid())) {
                    SpcyZltxwjType type = spcyZltxwjTypeService.getById(basicUpdate.getFtypeid());
                    if (type != null) {
                        basicUpdate.setFtype(type.getFlxmc());
                    }
                }
            }else {
                if (StringUtils.isNotBlank(basicUpdate.getFtypeid()) && !oldBean.getFtypeid().equals(basicUpdate.getFtypeid())){
                    SpcyZltxwjType type = spcyZltxwjTypeService.getById(basicUpdate.getFtypeid());
                    if (type != null) {
                        basicUpdate.setFtype(type.getFlxmc());
                    }
                }
            }

            spcyZltxwjFlowService.updateById(basicUpdate);
        } catch (IllegalAccessException e) {
            log.error("出错-保存申请事项【非法访问异常】,{}",e.getMessage());
        } catch (InvocationTargetException e) {
            log.error("出错-保存申请事项【调用TargetException】,{}",e.getMessage());
        }

        // 更新质量体系文件-修订状态
        if (StringUtils.isNotBlank(basicUpdate.getFpid())) {
            SpcyZltxwjBasic zltxwjBasic = spcyZltxwjBasicService.getById(basicUpdate.getFpid());
            if (zltxwjBasic != null && StringUtils.isNotBlank(zltxwjBasic.getFxdzt())
                    && StringUtils.isNotBlank(basicUpdate.getFxglx())
                    && !zltxwjBasic.getFxdzt().equals(basicUpdate.getFxglx())) {
                /*zltxwjBasic.setFxdzt(basicUpdate.getFxglx());
                spcyZltxwjBasicService.updateById(zltxwjBasic);*/

                LambdaUpdateWrapper<SpcyZltxwjBasic> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.eq(SpcyZltxwjBasic::getId, basicUpdate.getFpid());

                SpcyZltxwjBasic updateBean = new SpcyZltxwjBasic();
                updateBean.setFxdzt(basicUpdate.getFxglx());
                spcyZltxwjBasicService.update(updateBean, updateWrapper);
            }
        }

        String logContent = "基本信息修改: ";
        Map<String, Object> basicMap = ObjectToMapUtils.objectToMap(oldBean);
        logContent += LogUtils.BeanModifyMsg(basicUpdate,basicMap);

        if (job == null) {
            spcyLogService.addLogs(LogConstant.LOGS_ZLTXWJ, logContent, ywid, "质量体系文件", SpcyConstant.LOGS_SYS_TYPE_XG);
        }else {
            spcyLogService.addLogs(job.getFhjmc(), logContent, ywid, LogConstant.LOGS_SQSX_BASIC, SpcyConstant.LOGS_SYS_TYPE_XG);
        }

        return Result.ok("保存成功");
    }

    /**
     * 走完质量体系文件流程，将最终的文件移送到-资源库和历史库
     * @param zltxwjid 流程质量体系文件id
     */
    public Result ysFlowToZltxwjBasic(String zltxwjid){
        if (StringUtils.isBlank(zltxwjid)){
            return Result.error("质量体系文件参数为空");
        }
        boolean isAddBasic = true; // 是否更新资源库的内容

        SpcyZltxwjFlow flowZltxwj = spcyZltxwjFlowService.getById(zltxwjid);
        if (flowZltxwj == null){
            return Result.error("当前质量体系文件流程不存在，请刷新重试"+zltxwjid);
        }
        String basicId = "";

        // 判断是否绑定资源库,不存在，新增资源库，
        if (StringUtils.isBlank(flowZltxwj.getFpid())){
            SpcyZltxwjBasic newZltxwj = new SpcyZltxwjBasic();
            BeanUtil.copyProperties(flowZltxwj, newZltxwj);
            newZltxwj.setId(GetUuIdUtils.ReplaceUuId());
            newZltxwj.setFzt(SpcyConstant.Zltxwj_Zt_Yx);
            if (newZltxwj.getFssrq() == null) {
                newZltxwj.setFssrq(new Date());
            }
            if (newZltxwj.getFscrq() == null) {
                newZltxwj.setFscrq(new Date());
            }

            newZltxwj.setFwjlx(flowZltxwj.getFwjlx());
            newZltxwj.setFwjlj("");
            newZltxwj.setCreateTime(new Date());
            newZltxwj.setUpdateTime(new Date());
            spcyZltxwjBasicService.save(newZltxwj);

            String addTxwjLog = "添加质量体系文件质量员库：";
            addTxwjLog += LogUtils.MapToStringMethod(ObjectToMapUtils.objectToMap(newZltxwj));
            spcyLogService.addLogs(LogConstant.LOGS_ZLTXWJ,addTxwjLog,newZltxwj.getId(),SpcyConstant.LOGS_SYS_TYPE_XZ,SpcyConstant.LOGS_SYS_TYPE_XZ);

            basicId = newZltxwj.getId();
            flowZltxwj.setFpid(newZltxwj.getId());
            spcyZltxwjFlowService.updateById(flowZltxwj);
        }else {
            basicId = flowZltxwj.getFpid();
        }

        // 查询质量体系文件-资源库
        SpcyZltxwjBasic basicZltxwj = spcyZltxwjBasicService.getById(basicId);
        if (basicZltxwj == null){
            return Result.error("质量体系文件资源库不存在，请刷新重试"+basicId);
        }

        /** 1为pdf盖章文件 */
        int flowWjFlag = 0;
        if (flowZltxwj.getFwjlx().equals(".pdf") && StringUtils.isNotBlank(flowZltxwj.getFjdwjlj())){
            flowWjFlag = 1;
        }

        String basicWjlj = basicZltxwj.getFwjlj(); // 资源库-文件路径
        String historyWjlj = ""; // 历史库-文件路径

        /**
         * 将资源库文件-移送到历史库中
         */
        if (StringUtils.isNotBlank(basicWjlj)) {
            String wjHz = Util.getWjHz(basicWjlj);
            String wjml = "/" + SpcyConstant.Old_Zltxwj_File_Base_Url + "/" + DateConversionUtils.DateToMonthTwo(new Date());
            String uuidName = GetUuIdUtils.ReplaceUuId() + wjHz;

            historyWjlj = wjml + "/" + basicZltxwj.getFwjmc() + uuidName;

            if (businessConstant.isEnableZltxwnjMinio){
                InputStream minioInput = spcyMinioUtils.getObject(basicWjlj);
                if (minioInput == null){
                    return Result.error(basicWjlj+"文件流不存在！");
                }
                File file = localFileUploadUtils.asFile(minioInput, Util.getWjHz(basicWjlj));

                spcyMinioUtils.putFile(historyWjlj, file, wjHz);
            }else {

                File dir = new File(businessConstant.UPLOAD_FILE_ROOT + wjml);
                if (!dir.exists()) {
                    dir.mkdirs();
                }

                String newWjlj = businessConstant.UPLOAD_FILE_ROOT + historyWjlj;
                FileCopyUtils.copyFile(businessConstant.UPLOAD_FILE_ROOT + basicWjlj, newWjlj);
            }

        }else {
            /**
             * 将 流程文件 移入到 资源库 中
             */
            String wjHz = "";
            String flowWjUrl = "";
            if (flowWjFlag == 1){
                wjHz = Util.getWjHz(flowZltxwj.getFjdwjlj());
                flowWjUrl = flowZltxwj.getFjdwjlj();
            }else {
                wjHz = Util.getWjHz(flowZltxwj.getFwjlj());
                flowWjUrl = flowZltxwj.getFwjlj();
            }

            String wjml = "/" + SpcyConstant.Old_Zltxwj_File_Base_Url + "/" + DateConversionUtils.DateToYear(new Date());
            String uuidName = GetUuIdUtils.ReplaceUuId() + wjHz;
            historyWjlj = wjml + "/" + flowZltxwj.getFwjmc() + uuidName;

            if (businessConstant.isEnableZltxwnjMinio){
                InputStream minioInput = spcyMinioUtils.getObject(flowWjUrl);
                if (minioInput == null){
                    return Result.error(flowWjUrl+"文件流不存在！");
                }
                File file = localFileUploadUtils.asFile(minioInput, wjHz);

                spcyMinioUtils.putFile(historyWjlj, new File(file.getAbsolutePath()), wjHz);
            }else {

                File dir = new File(businessConstant.UPLOAD_FILE_ROOT + wjml);
                if (!dir.exists()) {
                    dir.mkdirs();
                }

                String newWjlj = businessConstant.UPLOAD_FILE_ROOT + historyWjlj;
                FileCopyUtils.copyFile(businessConstant.UPLOAD_FILE_ROOT + flowWjUrl, newWjlj);
            }
        }

        /**
         * 生成质量体系文件-历史库
         */
        SpcyZltxwjHistory history = new SpcyZltxwjHistory();
        BeanUtil.copyProperties(basicZltxwj, history);
        history.setId(GetUuIdUtils.ReplaceUuId());
        history.setFpid(basicId);
        history.setFwjlj(historyWjlj);
        history.setFwjlx(Util.getWjHz(historyWjlj));
        history.setCreateTime(new Date());
        history.setUpdateTime(new Date());
        history.setFzt(flowZltxwj.getFzt());
        spcyZltxwjHistoryService.save(history);

        /**
         * 将质量体系文件流程最终的文件-移送到资源库中
         */
        String newBasicWjlj = ""; // 新的资源库文件路径
        if (StringUtils.isNotBlank(flowZltxwj.getFwjlj()) && isAddBasic){

            String wjHz = "";
            String flowWjUrl = "";
            if (flowWjFlag == 1){
                wjHz = Util.getWjHz(flowZltxwj.getFjdwjlj());
                flowWjUrl = flowZltxwj.getFjdwjlj();
            }else {
                wjHz = Util.getWjHz(flowZltxwj.getFwjlj());
                flowWjUrl = flowZltxwj.getFwjlj();
            }

            String wjml = "/" + SpcyConstant.Zltxwj_File_Base_Url;
            if (StringUtils.isNotBlank(flowZltxwj.getFtype())){
                wjml += "/" + flowZltxwj.getFtype();
            }
            wjml += "/" + DateConversionUtils.DateToYear(new Date());

            newBasicWjlj = wjml + "/" + flowZltxwj.getFwjmc()+GetUuIdUtils.ReplaceUuId() + wjHz;

            if (businessConstant.isEnableZltxwnjMinio){
                InputStream minioInput = spcyMinioUtils.getObject(flowWjUrl);
                if (minioInput == null){
                    return Result.error(flowWjUrl+"文件流不存在！");
                }
                File file = localFileUploadUtils.asFile(minioInput, wjHz);

                spcyMinioUtils.putFile(newBasicWjlj, new File(file.getAbsolutePath()), wjHz);
            }else {
                File dir = new File(businessConstant.UPLOAD_FILE_ROOT + wjml);
                if (!dir.exists()) {
                    dir.mkdirs();
                }

                String newWjlj = businessConstant.UPLOAD_FILE_ROOT + newBasicWjlj;
                FileCopyUtils.copyFile(businessConstant.UPLOAD_FILE_ROOT + flowWjUrl, newWjlj);
            }

        }

        /**
         * 修改 质量体系文件资源库信息
         */
        if (isAddBasic) {
            String oldPdfUrl = basicZltxwj.getFpdfurl(); // 旧pdf路径

            Map<String, Object> oldBasicMap = ObjectToMapUtils.objectToMap(basicZltxwj);
            BeanUtil.copyProperties(flowZltxwj, basicZltxwj);
            basicZltxwj.setId(basicId);
            basicZltxwj.setFwjlj(newBasicWjlj);
            basicZltxwj.setFwjlx(Util.getWjHz(newBasicWjlj));

            if (basicZltxwj.getFssrq() == null) {
                basicZltxwj.setFssrq(new Date()); // 实施日期
            }
            if (basicZltxwj.getFscrq() == null) {
                basicZltxwj.setFscrq(new Date()); // 上传日期
            }
            basicZltxwj.setUpdateTime(new Date());
            basicZltxwj.setCreateTime(new Date());


            boolean isSx = false;
            if (StringUtils.isNotBlank(flowZltxwj.getFxglx()) && flowZltxwj.getFxglx().equals(SpcyConstant.Zltxwj_Xdlx_SX)){
                isSx = true;
                oldPdfUrl = null;
            }else {
                basicZltxwj.setFpdfurl("");
            }

            boolean updateFlag = spcyZltxwjBasicService.updateById(basicZltxwj);
            if (updateFlag) {

                if (StringUtils.isNotBlank(oldPdfUrl)){
                    localFileUploadUtils.deleteLocalFileUrlByZltxwj(oldPdfUrl); // 删除原资源库文件
                }
                if (StringUtils.isNotBlank(basicWjlj)) {
                    localFileUploadUtils.deleteLocalFileUrlByZltxwj(basicWjlj); // 删除原资源库文件
                }

                // 盖章
                this.zltxwjGzByZdlx(isSx, basicZltxwj);

                String zykLog = "修改资源库质量体系文件库：";
                zykLog += LogUtils.BeanModifyMsg(basicZltxwj, oldBasicMap);
                spcyLogService.addLogs("质量体系文件", zykLog, basicId, SpcyConstant.LOGS_SYS_TYPE_XG, SpcyConstant.LOGS_SYS_TYPE_XG);

            }
        }

        return Result.ok("操作成功");
    }

    /**
     * 质量体系文件盖章-根据修订类型
     */
    public void zltxwjGzByZdlx(boolean isSx, SpcyZltxwjBasic basicZltxwj){
        /*SpcyZltxwjBasic z = this.zltxwjToPdf(basicZltxwj, false); // 生成pdf版文件
        hnCaUtils.fileCaInZltxwjBasic(z.getId(), z, isSx);*/
        zltxwjToPdf(basicZltxwj, false, true, isSx);
    }

    /**
     * 生产资源库文件pdf版
     */
    public SpcyZltxwjBasic zltxwjToPdf(SpcyZltxwjBasic basicZltxwj){
        return zltxwjToPdf(basicZltxwj, true, false, false);
    }
    public SpcyZltxwjBasic zltxwjToPdf(SpcyZltxwjBasic basicZltxwj, boolean isDelete){
        return zltxwjToPdf(basicZltxwj, isDelete, false, false);
    }

    /**
     * @param isDelete  是否删除： true: 删除pdf文件
     * @param isGz 是否盖章 true: 盖章
     * @param isSx 是否盖章失效 true: 盖失效； false: 盖受控
     * @return
     */
    public SpcyZltxwjBasic zltxwjToPdf(SpcyZltxwjBasic basicZltxwj, boolean isDelete, boolean isGz, boolean isSx){
        if (isDelete) {
            if (StringUtils.isNotBlank(basicZltxwj.getFpdfurl())) {
                localFileUploadUtils.deleteLocalFileUrlByZltxwj(basicZltxwj.getFpdfurl());
            }
        }else {
            if (StringUtils.isNotBlank(basicZltxwj.getFpdfurl())){
                return basicZltxwj;
            }
        }

        if (StringUtils.isBlank(basicZltxwj.getFwjlx())){
            return basicZltxwj;
        }

        if (StringUtils.isBlank(basicZltxwj.getFwjlj())){
            return basicZltxwj;
        }

        boolean isPdf = false;
        if (basicZltxwj.getFwjlx().equals(".pdf")){
            isPdf = true;
        }else {
            // 文档才能转换
            if (!(basicZltxwj.getFwjlx().equals(".doc") || basicZltxwj.getFwjlx().equals(".docx"))) {
                return basicZltxwj;
            }
        }

        String wordUrl = ""; // 文档路径
        String parMl = ""; // pdf文件父路径
        if (businessConstant.isEnableZltxwnjMinio) {
            parMl = businessConstant.TEMPORARY_UPLOAD_MKDIR_ROOT + "/" + SpcyConstant.TEMP_WJJL_CHILD_URL;
            InputStream minioInput = spcyMinioUtils.getObject(basicZltxwj.getFwjlj());
            if (minioInput == null){
                return basicZltxwj;
            }
            File file = localFileUploadUtils.asFile(minioInput, Util.getWjHz(basicZltxwj.getFwjlj()));
            wordUrl = file.getAbsolutePath();
        }else {
            wordUrl = businessConstant.UPLOAD_FILE_ROOT + basicZltxwj.getFwjlj();

            parMl = businessConstant.UPLOAD_FILE_ROOT;
        }

        /**
         * 生产pdf文件版
         */
        String ml = "/" + SpcyConstant.Zltxwj_File_Base_Url + "/pdf/" + DateConversionUtils.DateToYear(new Date());
        File dir = new File(parMl + ml);
        if (!dir.exists()){
            dir.mkdirs();
        }
        String pdfUrl = ml + "/"+ GetUuIdUtils.ReplaceUuId()+".pdf";

        if (isPdf){
            boolean copyFlag = FileCopyUtils.copyFile(wordUrl, parMl+pdfUrl); // 复制文件
            if (!copyFlag){
                return basicZltxwj;
            }
        }else {
            wordPdfUtils.wordToPdf(wordUrl, parMl + pdfUrl);
        }

        // 盖章
        if (isGz){
            Result result = hnCaUtils.fileCaInZltxwjBasicInLocal(parMl + pdfUrl, isSx);
            if (!result.isSuccess()){
                return basicZltxwj;
            }
        }

        boolean flag = true;
        if (businessConstant.isEnableZltxwnjMinio) {
            flag = spcyMinioUtils.putFlagFile(pdfUrl, new File(parMl + pdfUrl), Util.getWjHz(".pdf"));
        }

        if (flag) {
            basicZltxwj.setFpdfurl(pdfUrl);

            LambdaUpdateWrapper<SpcyZltxwjBasic> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(SpcyZltxwjBasic::getId, basicZltxwj.getId());

            SpcyZltxwjBasic updateBean = new SpcyZltxwjBasic();
            updateBean.setFpdfurl(pdfUrl);
            spcyZltxwjBasicService.update(updateBean, updateWrapper);
        }

        return basicZltxwj;
    }

    /** 历史文件库下载pdf */
    public void historyZltxwjToTempPdf(SpcyZltxwjHistory basicZltxwj, String wjhz, HttpServletResponse response){
        this.historyZltxwjToTempPdf(basicZltxwj, wjhz, false, null, response);
    }
    public void historyZltxwjToTempPdf(SpcyZltxwjHistory basicZltxwj, String wjhz, boolean isSy, String symc, HttpServletResponse response){
        String wordUrl = ""; // 文档路径
        String parMl = ""; // pdf文件父路径
        if (businessConstant.isEnableZltxwnjMinio) {
            parMl = businessConstant.TEMPORARY_UPLOAD_MKDIR_ROOT + "/" + SpcyConstant.TEMP_WJJL_CHILD_URL;
            InputStream minioInput = spcyMinioUtils.getObject(basicZltxwj.getFwjlj());
            if (minioInput == null){
                throw new BusinessException("文件流为空！");
            }

            File file = localFileUploadUtils.asFile(minioInput, Util.getWjHz(basicZltxwj.getFwjlj()));
            wordUrl = file.getAbsolutePath();
        }else {
            wordUrl = businessConstant.UPLOAD_FILE_ROOT + basicZltxwj.getFwjlj();

            parMl = businessConstant.TEMPORARY_UPLOAD_MKDIR_ROOT + "/" + SpcyConstant.TEMP_WJJL_CHILD_URL;
        }

        /**
         * 生产pdf文件版
         */
        String pdfUrl = "/" + GetUuIdUtils.ReplaceUuId() + ".pdf";
        if (wjhz.equals(".pdf")){
            boolean copyFlag = FileCopyUtils.copyFile(wordUrl, parMl+pdfUrl); // 复制文件
            if (!copyFlag){
                throw new BusinessException("文件流为空！");
            }
        }else {
            wordPdfUtils.wordToPdf(wordUrl, parMl + pdfUrl);
        }

        if (isSy){
            if (StringUtils.isBlank(symc)){
                localFileUploadUtils.ejzLocalFileByZdyFile(new File(parMl + pdfUrl), response);
            }else {
                localFileUploadUtils.ejzLocalFileSy(parMl + pdfUrl, ".pdf", symc, response);
            }
        }else {
            localFileUploadUtils.ejzLocalFileByZdyFile(new File(parMl + pdfUrl), response);
        }
    }

    /**
     * 批量打印流转审批表
     * @param map ids | 质量体系文件zltxwjid,多个英文逗号拼接
     * @return
     */
    public HttpResult queryPrintZltxwjTable(HashMap<String,String> map){
        Map resultMap = new HashMap();

        String ids = map.get("ids");
        if (StringUtils.isBlank(ids)){
            return HttpResult.error("参数不能为空");
        }
        List<String> idsList = StringPatternUtils.getListByIds(ids);
        if (CollectionUtils.isEmpty(idsList)){
            return HttpResult.error("传递的参数规则错误，请联系管理员");
        }
        List<SpcyZltxwjFlow> txwjList = spcyZltxwjFlowService.listByIds(idsList);
        if (CollectionUtils.isEmpty(txwjList)){
            return HttpResult.error("所选的体系文件不存在，请刷新并重试");
        }
        List<Map> resultList = new ArrayList<>();
        for (SpcyZltxwjFlow flow : txwjList){
            Map result = new HashMap();
            result.put("zltxwj",flow);

            List<Map> jobMapList = new ArrayList<>();

            // 当前记录的流程记录
            List<SpcySqsxJob> jobList = spcySqsxJobService.list(new LambdaQueryWrapper<SpcySqsxJob>()
                    .eq(SpcySqsxJob::getFpid, flow.getId())
                    .like(SpcySqsxJob::getFlcmc, SpcyFlowConstant.ZLTXWJ_LCMC)
                    .orderByAsc(SpcySqsxJob::getFfssj));

            if (CollectionUtils.isNotEmpty(jobList)){
                Map jobMap = null;
                for (SpcySqsxJob job : jobList){
                    jobMap = new HashMap();
                    jobMap.put("fhjmc", job.getFhjmc()); // 环节名称
                    jobMap.put("fuserid", job.getFdbrid().split(",|，")[0]); // 办理id
                    jobMap.put("username", job.getFdbr().split(",|，")[0]); // 姓名
                    jobMap.put("fblsj", job.getFblsj()); // 办理时间
                    jobMap.put("opinion", job.getFblyj()); // 办理意见
                    jobMapList.add(jobMap);
                }
            }
            result.put("jobList",jobMapList);
            resultList.add(result);
        }

        resultMap.put("printList", resultList);
        return HttpResult.ok(resultMap);
    }

    /**
     * 上传文件-宣贯学习文件
     * @param uploadFile 文件数组
     * @param zltxwjid 流程质量体系文件id
     */
    public Result uploadXgxxFile(MultipartFile[] uploadFile, String zltxwjid){

        if (StringUtils.isEmpty(zltxwjid)){
            return Result.error("质量体系文件参数不能为空");
        }

        if (uploadFile == null || uploadFile.length == 0) {
            return Result.error("上传失败,请先选择文件");
        }

        for (MultipartFile file : uploadFile) {

            String originalFilename = file.getOriginalFilename();
            // 文件类型
            String wjlx = originalFilename.substring(originalFilename.lastIndexOf("."));

            // 文件名
            String fileName = file.getOriginalFilename().substring(0, file.getOriginalFilename().lastIndexOf("."));

            SpcySqsxWjjl spcySqsxWjjl = new SpcySqsxWjjl();

            String sjmc = SpcyFlowConstant.FILE_TYPE_XGQKFJ + GetUuIdUtils.ReplaceUuId();

            String wjccmc = sjmc + wjlx;

            String ml = SpcyConstant.Flow_Zltxwj_File_Base_Url + "/" + DateConversionUtils.DateToYear(new Date());

            localFileUploadUtils.uploadZdyFile(file, wjccmc, ml, true); // 上传文件

            String Id = GetUuIdUtils.NotReplaceUuId();
            spcySqsxWjjl.setId(Id);
            spcySqsxWjjl.setFpid(zltxwjid);
            spcySqsxWjjl.setFwjxsmc(fileName);
            spcySqsxWjjl.setFwjlx(wjlx);
            spcySqsxWjjl.setFwjlx1(SpcyFlowConstant.FILE_TYPE_XGQKFJ);
            spcySqsxWjjl.setFwjlx2(SpcyFlowConstant.FILE_TYPE_XGQKFJ);
            spcySqsxWjjl.setFwjccmc(wjccmc);
            String cflj = "/" + ml + "/" + wjccmc;
            spcySqsxWjjl.setFcflj(cflj);

            boolean flag = spcySqsxWjjlService.save(spcySqsxWjjl);
            if (flag) {
                String czContent = "宣传学习-上传文件: ";
                Map<String, Object> wjjlMap = ObjectToMapUtils.objectToMap(spcySqsxWjjl);
                czContent += LogUtils.MapToStringMethod(wjjlMap);
                spcyLogService.addLogs(LogConstant.LOGS_ZLTXWJ + "-宣传学习", czContent, zltxwjid, LogConstant.LOGS_SQSX_WJJL, SpcyConstant.LOGS_SYS_TYPE_BC);
            }

        }

        return Result.ok("操作成功");
    }

    /**
     * 下载文件-宣贯学习文件
     * @param id 文件记录id
     */
    public void downloadXgxxFile(String id, HttpServletResponse response){
        if (StringUtils.isBlank(id)){
            throw new BusinessException("下载失败，文件记录参数为空！");
        }

        SpcySqsxWjjl wjjl = spcySqsxWjjlService.getById(id);
        if (wjjl == null){
            throw new BusinessException("下载失败，文件记录不存在，请刷新重试！");
        }
        if (StringUtils.isBlank(wjjl.getFcflj())){
            throw new BusinessException("下载失败，文件记录中的附件为空！");
        }

        localFileUploadUtils.ejzLocalFileURlByZdy(wjjl.getFcflj(), true, response);
    }

    /**
     * 删除文件-宣贯学习文件
     * @param id 文件记录id
     */
    public Result deleteXgxxFile(String id){
        if (StringUtils.isBlank(id)){
            throw new BusinessException("删除文件失败，文件记录参数为空！");
        }

        SpcySqsxWjjl wjjl = spcySqsxWjjlService.getById(id);
        if (wjjl == null){
            throw new BusinessException("删除文件失败，文件记录不存在，请刷新重试！");
        }

        spcySqsxWjjlService.removeById(id);

        if (StringUtils.isNotBlank(wjjl.getFcflj())) {
            localFileUploadUtils.deleteLocalFileUrlByZdy(wjjl.getFcflj(),true);
        }


        return Result.ok("操作成功");
    }

    /**
     * 查询文件-宣贯学习文件
     * @param zltxwjid 流程质量体系文件id
     */
    public HttpResult queryXgxxFile(String zltxwjid){
        if (StringUtils.isBlank(zltxwjid)){
            return HttpResult.error("参数为空！");
        }
        List<SpcySqsxWjjl> wjjlList = spcySqsxWjjlService.list(new LambdaQueryWrapper<SpcySqsxWjjl>()
                .eq(SpcySqsxWjjl::getFpid, zltxwjid)
                .eq(SpcySqsxWjjl::getFwjlx1, SpcyFlowConstant.FILE_TYPE_XGQKFJ)
                .orderByDesc(SpcySqsxWjjl::getCreateTime));

        return HttpResult.ok(wjjlList);
    }
}
